package com.alibaba.cloud.base.business.user.service;

import com.alibaba.cloud.base.auth.token.OauthToken;
import com.alibaba.cloud.base.business.user.controller.LoginUserController;
import com.alibaba.cloud.base.business.user.dao.LoginUserDao;
import com.alibaba.cloud.base.business.user.domain.LoginUser;
import com.alibaba.cloud.base.tips.AuthTips;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.framework.constant.Constant;
import com.alibaba.framework.domain.ResponseWrapper;
import com.alibaba.framework.exception.BusinessException;
import com.alibaba.framework.exception.ResponseCode;
import com.alibaba.framework.tips.TipKey;
import com.alibaba.framework.tips.TipMess;
import com.alibaba.framework.utils.DateUtil;
import com.alibaba.framework.utils.EncryptUtil;
import com.alibaba.framework.utils.HttpClientUtil;
import com.alibaba.framework.utils.UUIDUtil;
import com.alibaba.framework.wrapper.RedisWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class LoginUserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoginUserController.class);

    private AtomicInteger visits = new AtomicInteger(1);

    @Resource
    private LoginUserDao userDao;

    @Autowired
    private RedisWrapper<String, Object> redisWrapper;

    /**
     * 获取登录对象
     */
    public LoginUser getLoginUser(String userId) {

        // 10s内不允许再次访问
/*        Boolean flag = redisWrapper.putIfAbsentWithExpireTime(TipKey.REDIS_NOT_PERMIT_ACCESS_AGAIN, "getLoginUser", 10, TimeUnit.SECONDS);
        if (!flag) {
            throw new BusinessException(TipMess.USER_NOT_PERMIT_ACCESS_AGAIN);
        }*/

        // 30s内不允许访问超过三次
        Boolean getLoginUser = redisWrapper.putIfAbsentWithExpireTime(TipKey.REDIS_NOT_PERMIT_ACCESS_OVER_3, "getLoginUser", 30, TimeUnit.SECONDS);
        /*if (getLoginUser) {
            this.visits.set(1);
        } else {
            int visits = this.visits.incrementAndGet();
            if (visits > 3) {
                throw new BusinessException(TipMess.USER_NOT_PERMIT_ACCESS_OVER_3);
            }
        }*/

        return userDao.getLoginUser(userId);
    }

    /**
     * 用户注册
     * 处理并发问题: 1.数据库唯一索引
     *             2.悲观锁实现
     */
    @Transactional(rollbackFor = Exception.class)
    public void registerLoginUser(LoginUser user) {

        synchronized (LoginUserService.class) {
            List<LoginUser> userList = userDao.getLoginUserByUsername(user.getUsername());
            if (userList.size() > 0) {
                throw new BusinessException(TipMess.USER_REGISTER_USERNAME_REPEAT);
            }
            user.setId(UUIDUtil.uuid());
            user.setPassword(EncryptUtil.BCryptEncoderWrapper(user.getPassword()));
            userDao.registerLoginUser(user);
        }
    }

    /**
     * 用户登录
     */
    @Transactional(rollbackFor = Exception.class)
    public ResponseWrapper login(LoginUser registerUser) {
        String username = registerUser.getUsername();
        String password = registerUser.getPassword();
        // 请求授权服务认证并颁发令牌
        String gainTokenUrl = "http://localhost:9094/auth/oauth/token";
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("grant_type", "password");
        paramMap.put("username", username);
        paramMap.put("password", password);

        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("Authorization", "Basic YWxpX2NsaWVudDphbGlfc2VjcmV0");

        ResponseWrapper responseWrapper = HttpClientUtil.httpPost(gainTokenUrl, paramMap, HttpClientUtil.CONTENT_TYPE.KEY_VALUE, headerMap);
        Object data = responseWrapper.getData();
        LOGGER.info("Oauth2回调接口响应：{}", data);

        OauthToken oauthToken = null;
        if (responseWrapper.getCode() == ResponseCode.SUCCESS_CODE) {
            oauthToken = JSONObject.parseObject(data + "", OauthToken.class);
        } else {
            // oauth异常先简单处理，后续考虑添加异常转换器
            JSONObject obj = JSONObject.parseObject(data + "");
            if((data + "").contains("unauthorized")) {
                return ResponseWrapper.Fail(obj.get("error_description").toString(), data);
            }
            if ((data + "").contains("Bad credentials")) {
                return ResponseWrapper.Fail(AuthTips.NOT_VALID_CREDENTIALS, data);
            }
            return ResponseWrapper.Fail(data);
        }
        if (Objects.isNull(oauthToken)) {
            return ResponseWrapper.Fail("获取Token为空!");
        }
        String token = oauthToken.getAccess_token();
        LOGGER.info("登录成功，获取token：{}", oauthToken);
        String key = "user:token:" + token;
        redisWrapper.putValueWithExpireTime(key, oauthToken, Constant.EXPIRE_TIME_HOUR, TimeUnit.HOURS);

        String dateTime = DateUtil.getDateTime();
        String expireTime = DateUtil.getExpireTime(Constant.EXPIRE_TIME_HOUR);
        registerUser.setCreateTime(DateUtil.getDateTime());
        registerUser.setExpireTime(expireTime);
        registerUser.setToken(token);
        registerUser.setLoginTime(dateTime);
        registerUser.setUpdateTime(dateTime);
        userDao.updateLoginUserByUsername(registerUser);
        return ResponseWrapper.Success(token);
    }

    /**
     * 用户注销
     */
    public Boolean logoutUser(String userId) {

        return redisWrapper.delWithKey(userId);
    }

    /**
     * @descript 根据用户名查询用户
     * @author focus
     * @date 2025/9/5
     */
    public LoginUser getLoginUserByUsername(String username) {

        QueryWrapper<LoginUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        return userDao.selectOne(wrapper);
    }
}
